package com.gusto.engine.semsim.measures.utils;

import java.util.Calendar;
import java.util.GregorianCalendar;

import org.apache.log4j.Logger;

/**
 * <p>Utilities for date difference calculation.</p>
 * 
 * @author amokrane.belloui@gmail.com
 *
 */
public class DateDiff {
	
	private Logger log = Logger.getLogger(getClass());
	
	public class Diff {
		public Integer days;
		public Integer months;
		public Integer years;
		public String toString() {
			String str = ""; 
			str += (days);
			str += (" days ");
			str += (months);
			str += (" months ");
			str += (years);
			str += (" years ");
			return str;
		}
	}
	

    /** 
     * Compute the difference between two dates in years, months, and days. 
     * The result is returned in a concatenated integer value of the form
     * ymmdd. So the difference between Apr 20, 2003 and Apr 15, 2025 would
     * be 211126 (21 years, 11 months, and 26 days) since 21 years and 
     * 11 months gets you to May 20 2025, there are 31 days in May of 2025, 
     * and it takes 25 days to go from May 20 2025 to April 15 2025! To split 
     * the values off, 
     * #years = return value / 10000, 
     * #months = return value % 10000 / 100
     * #days = return value % 100. 
     * This method will return a negative value if the 'from' value is after the 
     * 'to' value (i.e. getDiff( from, to) = -getDiff( to, from )). 
     * 
     * @param pFrom The time to compute the difference from.
     * @param pTo Date The time to compute the difference to.
     * 
     * @return int The differenct in the two dates in the form ymmdd.
     */
	public Diff getDiff( java.util.Date pFrom, java.util.Date pTo ) {
		if ( pFrom.after( pTo ) ) {
            java.util.Date pTemp = pTo;
            pTo = pFrom;
            pFrom = pTemp;
            log.debug("fromDate " + pFrom + " is after toDate " + pTo + ", inversing");
        }
        return getDiff2(pFrom, pTo);
	}
	
	private Diff getDiff2( java.util.Date pFrom, java.util.Date pTo ) {
        Calendar lFrom = new GregorianCalendar();
        lFrom.setTime( pFrom );
        Calendar lTo = new GregorianCalendar();
        lTo.setTime( pTo );
 
        int lFromYear = lFrom.get( Calendar.YEAR );
        int lFromMonth = lFrom.get( Calendar.MONTH );
        int lFromDay = lFrom.get( Calendar.DAY_OF_MONTH );
 
        int lToYear = lTo.get( Calendar.YEAR );
        int lToMonth = lTo.get( Calendar.MONTH );
        int lToDay = lTo.get( Calendar.DAY_OF_MONTH );
 
        int lYearDiff = lToYear - lFromYear;
        int lMonthDiff = lToMonth - lFromMonth;
        int lDayDiff = lToDay - lFromDay;
 
        if ( lDayDiff < 0 )
        {
            lMonthDiff--;
            Calendar lTemp = new GregorianCalendar();
            lTemp.setTime( pTo );
            lTemp.add( Calendar.MONTH, -1 );
            lDayDiff = lTemp.getActualMaximum( Calendar.DAY_OF_MONTH ) + lDayDiff;
        }
 
        if ( lMonthDiff < 0 )
        {
            lYearDiff--;
            lMonthDiff = 12 + lMonthDiff;
        }
        
        Diff diff = new Diff();
        diff.days = lDayDiff;
        diff.months = lMonthDiff;
        diff.years = lYearDiff;
        
        log.debug("Diference between (" + pFrom + " " + pTo + ") " + diff);
        
        return diff;
    }
	
	private boolean IsLeapYear(int year) {
    	if(year%400==0)
			return true;
		else if ((year>1582) && (year%100)==0)
			return false;
		else if ((year % 4)==0)
			return true;
		return false;
	}
	
	//function to validate whether a year is a leap year
	protected void validate(int m, int d, int y) {
		boolean ly=IsLeapYear(y);
		if(y<100) {
			throw new IllegalArgumentException();
		}
		//year validation
		
		if (m==4 || m==6 || m==7 || m==11) {
			if (d==31) {
				throw new IllegalArgumentException();
			}
			//months with 30 days validation (don't need 31 day validation 
			//you can't put in more than 31 days
		}
		else if (m==2) {//if feb...
			if(!ly) {//if not leap year... 
				if (d>28) { //day validation
					throw new IllegalArgumentException();
				}
			}
			else {
				if (d>29) { //day validation
					throw new IllegalArgumentException();
				}
			}
		}
	}

}
